
let middlewares=[
     async (ctx,next)=>{
        console.log('Start:',1);
        await next();
        console.log('End:',1);
    },
    async (ctx,next)=>{
        console.log('Start:',2);
        await next();
        console.log('End:',2);
    },
    async (ctx,next)=>{
        console.log('Start:',3);
        await next();
        console.log('End:',3);
    }
];


(()=>{
    let fn=compose(middlewares);
    console.log(fn);
    fn('ctx').then(ret=>console.log('ret:',ret));
})();

function compose(middlewares) {

    return ctx=>{
        return (function next(i){
            let fn=middlewares[i];

            if(!fn)return Promise.resolve();
            try{
                return Promise.resolve(fn(ctx,()=>{
                    return next(++i);
                }));
            }catch(err){
                return Promise.reject(err);
            }
        })(0);
    }
}